package com.zjpavt.client.command.todaycommand;

import com.zjpavt.client.hal.LoopManager;
import com.zjpavt.client.job.JobManager;
import com.zjpavt.client.job.JobRunner;
import com.zjpavt.client.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.time.Duration;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;

/**
 * 当天定时指令控制管理类
 * @author: gxy
 */
public class TodayCommandManager {
    private static final Logger log = LoggerFactory.getLogger(TodayCommandManager.class);
    private static final TodayCommandManager TODAY_COMMAND_MANAGER = new TodayCommandManager();
    /**
     * 作为共享数据
     */
    private final TodayCommandBean todayCommandBean;
    private static final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(Consts.TIME_FORMAT);

    private TodayCommandManager() {
        todayCommandBean = new TodayCommandBean();
        try {
            String pStartTime = PropertiesUtil.getProperties(ClientConfig.DEVICE_TIMER_CONFIG_NAME, Consts.KEY_TIMER_START_TIME);
            String pCloseTime = PropertiesUtil.getProperties(ClientConfig.DEVICE_TIMER_CONFIG_NAME, Consts.KEY_TIMER_CLOSE_TIME);
            String pTodayTimerCommand = PropertiesUtil.getProperties(ClientConfig.DEVICE_TIMER_CONFIG_NAME, Consts.KEY_TIMER_COMMAND);
            if (!StringUtil.isNullOrEmpty(pCloseTime, pStartTime, pTodayTimerCommand)) {
                synchronized (todayCommandBean) {
                    todayCommandBean.setCloseTime(pCloseTime);
                    todayCommandBean.setStartTime(pStartTime);
                    todayCommandBean.setTodayTimerCommand(pTodayTimerCommand);
                }
            }
        } catch (IOException e) {
            log.error(LoggerUtil.convertException2String(e));
        }
    }

    /**
     * @return 单例获取当天定时器控制类
     */
    public static TodayCommandManager getInstance() {
        return TODAY_COMMAND_MANAGER;
    }

    /**
     * 保存定时器指令（老的api用于设置服务器设置当天定时指令）
     *
     * @param start   开启时间
     * @param end     结束时间
     * @param command 指令
     */
    public boolean setTodayTimerCommand(String start, String end, String command) {
        if (StringUtil.isNullOrEmpty(start, end, command)) {
            return false;
        }
        boolean result = false;
        try {
            synchronized (todayCommandBean) {
                checkAndSet(start, end, command);
                saveTodayTimer();
            }
            result = true;
        } catch (IOException e) {
            log.error(LoggerUtil.convertException2String(e));
        }
        return result;
    }

    /**
     * 保存定时器指令（页面设置的时候方便操作）
     *
     * @param start   开启时间
     * @param end     结束时间
     * @param command 指令
     */
    public void setTodayTimerCommand(LocalTime start, LocalTime end, String command) {
        if (start == null || end == null) {
            return;
        }
        try {
            String startTime = start.format(TIME_FORMATTER);
            String closeTime = end.format(TIME_FORMATTER);
            synchronized (todayCommandBean) {
                checkAndSet(startTime, closeTime, command);
                saveTodayTimer();
            }
        } catch (IOException e) {
            log.error(LoggerUtil.convertException2String(e));
        }
    }

    public String getTodayTimer() {
        StringBuilder sb = new StringBuilder();
        synchronized (todayCommandBean) {
            sb.append(todayCommandBean.getStartTime()).append("_")
            .append(todayCommandBean.getCloseTime()).append("_")
            .append(todayCommandBean.getTodayTimerCommand());
        }
        return sb.toString();
    }


    /**
     * @return 是否清除定时器指令成功
     */
    public boolean cleanTodayTimer() {
        try {
            synchronized (todayCommandBean) {
                todayCommandBean.initData();
                saveTodayTimer();
            }
            return true;
        } catch (IOException e) {
            log.error(LoggerUtil.convertException2String(e));
            return false;
        }
    }

    private void checkAndSet(String startTime, String closeTime, String command) {
        if (startTime.equals(closeTime)) {
            todayCommandBean.initData();
        } else {
            todayCommandBean.setCloseTime(closeTime);
            todayCommandBean.setStartTime(startTime);
            todayCommandBean.setTodayTimerCommand(command);
        }
    }

    /**
     * 在当天定时器设置完后，一定要取消之前的发布，重新发布新的定时器，并刷新定时器指令
     *
     * @throws IOException 保存失败
     */
    private void saveTodayTimer() throws IOException {
        PropertiesUtil.setPropertyOrReplace(ClientConfig.DEVICE_TIMER_CONFIG_NAME, Consts.KEY_TIMER_START_TIME, todayCommandBean.getStartTime());
        PropertiesUtil.setPropertyOrReplace(ClientConfig.DEVICE_TIMER_CONFIG_NAME, Consts.KEY_TIMER_CLOSE_TIME, todayCommandBean.getCloseTime());
        PropertiesUtil.setPropertyOrReplace(ClientConfig.DEVICE_TIMER_CONFIG_NAME, Consts.KEY_TIMER_COMMAND, todayCommandBean.getTodayTimerCommand());
        JobManager.getInstance().cancelTodayTimerJob();
        JobRunner.getInstance().sendTodayTimerCommand();
        JobRunner.getInstance().refreshTodayTimerCommand();
    }

    /**
     * 时间有效性校验 是否开始时间小于结束时间
     *
     * @param start 开始时间
     * @param end 结束时间
     * @return 是否通过
     */
    private boolean isDateValid(String start, String end) {
        try {
            final Duration between = Duration.between(LocalTime.parse(start), LocalTime.parse(end));
            return between.toMillis() > 0;
        } catch (DateTimeParseException e) {
            log.error(LoggerUtil.convertException2String(e));
            return false;
        }
    }

    public boolean isValidCommand() {
        synchronized (todayCommandBean) {
            return !todayCommandBean.startTime.equals(todayCommandBean.closeTime);
        }
    }
    /**
     * @param date 时间点
     * @return 获取某个时刻的指令
     */
    public String getNowTodayCommand(LocalTime date) {
        if (date == null || !isValidCommand()) {
            return null;
        }
        try {
            synchronized (todayCommandBean) {
                if (isDateValid(todayCommandBean.getStartTime(),todayCommandBean.getCloseTime())) {
                    Duration startToNow = Duration.between(todayCommandBean.getLocalStartTime(), date);
                    Duration nowToClose = Duration.between(date, todayCommandBean.getLocalCloseTime());
                    if (startToNow.toMillis() >= 0 && nowToClose.toMillis() >= 0) {
                        return todayCommandBean.getTodayTimerCommand();
                    }
                } else {
                    Duration startToNow = Duration.between(todayCommandBean.getLocalStartTime(), date);
                    Duration nowToClose = Duration.between(date, todayCommandBean.getLocalCloseTime());
                    if (startToNow.toMillis() <= 0 || nowToClose.toMillis() <= 0) {
                        return todayCommandBean.getTodayTimerCommand();
                    }
                }
            }
        } catch (DateTimeParseException e) {
            log.error(LoggerUtil.convertException2String(e));
        }
        return null;
    }

    public LocalTime getLocalCloseTime() {
        synchronized (todayCommandBean) {
            return todayCommandBean.getLocalCloseTime();
        }
    }

    public LocalTime getLocalStartTime() {
        synchronized (todayCommandBean) {
            return todayCommandBean.getLocalStartTime();
        }
    }

    public TodayCommandBean getCopyTodayCommand() {
        synchronized (todayCommandBean) {
            TodayCommandBean result = new TodayCommandBean(todayCommandBean.startTime, todayCommandBean.closeTime, todayCommandBean.todayTimerCommand);
            return result;
        }
    }

    /**
     * 定时器实体类 (获取每个单一数据时时原子性，但是分开获取是非原子性，自行外面加上单例的锁)
     *
     * @author: gxy
     */
    public class TodayCommandBean {
        private static final String DEFAULT_TIME = "00:00:00";
        private final DateTimeFormatter TIME_FORMATTER = DateTimeFormatter.ofPattern(Consts.TIME_FORMAT);
        /**
         * 定时器开始时间
         */
        private String startTime;
        /**
         * 定时器结束时间
         */
        private String closeTime;
        /**
         * 定时器的指令
         */
        private String todayTimerCommand;

        /**
         * 当前类作为共享数据，（为防止创建多个设置为单例）
         *
         * @return 获取定时器类
         */

        private TodayCommandBean() {
            initData();
        }

        private TodayCommandBean(String startTime, String closeTime, String todayTimerCommand) {
            this.startTime = startTime;
            this.closeTime = closeTime;
            this.todayTimerCommand = todayTimerCommand;
        }

        /**
         * @return 用于用户获取数据时调用的，保证了线程安全。
         */

        public String getStartTime() {
            return startTime;
        }


        public String getCloseTime() {
            return closeTime;
        }

        public String getTodayTimerCommand() {
            return todayTimerCommand;
        }

        /**
         * @return 定时器开始时间的LocalTime
         */
        public LocalTime getLocalStartTime() {
            return LocalTime.parse(startTime, TIME_FORMATTER);
        }

        /**
         * @return 定时器关闭时间的LocalTime
         */
        public LocalTime getLocalCloseTime() {
            return LocalTime.parse(closeTime, TIME_FORMATTER);
        }

        public void setStartTime(String startTime) {
            this.startTime = startTime;
        }

        public void setCloseTime(String closeTime) {
            this.closeTime = closeTime;
        }

        public void setTodayTimerCommand(String todayTimerCommand) {
            this.todayTimerCommand = todayTimerCommand;
        }

        public void initData() {
            this.startTime = DEFAULT_TIME;
            this.closeTime = DEFAULT_TIME;
            this.todayTimerCommand = LoopManager.getInstance().getAllClosedCommand();
        }
    }
}
